package org.moonlight.jvm.classfile.attribute.debuginfo;

import lombok.Getter;
import org.moonlight.jvm.classfile.ClassReader;
import org.moonlight.jvm.classfile.attribute.AttributeInfo;

/**
 *
 * LineNumberTable 属性表存放方法的行号信息，LocalVariableTable 属性表中存放方法的局部变量信息。
 * 这两种属性和 SourceFile 属性都属于调试信息，都不是运行时必需的。
 *
 * LineNumberTable和LocalVariableTable属性表在结构上很像。其结构定义如下:
 *   LineNumberTable_attribute {
 *       u2 attribute_name_index
 *       u4 attribute_length
 *       u2 line_number_table_length
 *       {
 *         u2 start_pc;
 *         u2 line_number;
 *       } line_number_table[line_number_table_length]
 *   }
 *
 * @author Moonlight
 * @createTime 2023/8/15 17:06
 **/
@Getter
public class LineNumberTableAttribute implements AttributeInfo {

    private LineNumberTableEntry[] lineNumberTable;

    @Override
    public void readInfo(ClassReader reader) {
        int lineNumberTableLength = reader.readUint16();
        LineNumberTableEntry[] lineNumberTable = new LineNumberTableEntry[lineNumberTableLength];
        for (int i = 0; i < lineNumberTableLength; i++) {
            lineNumberTable[i] = new LineNumberTableEntry(reader.readUint16(), reader.readUint16());
        }
        this.lineNumberTable = lineNumberTable;
    }

    public int getLineNumber(int pc) {
        for (int i = this.lineNumberTable.length - 1; i >= 0; i--) {
            LineNumberTableEntry entry = this.lineNumberTable[i];
            if (pc >= entry.startPc) {
                return entry.lineNumber;
            }
        }
        return -1;
    }

    @Getter
    static class LineNumberTableEntry {
        private final int startPc;
        private final int lineNumber;

        public LineNumberTableEntry(int startPc, int lineNumber) {
            this.startPc = startPc;
            this.lineNumber = lineNumber;
        }

    }

}
